package co.sanduche.util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;

import android.util.Log;
import co.sanduche.services.EPClient;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import com.fasterxml.jackson.jr.ob.JSON;
import com.fasterxml.jackson.jr.ob.JSONObjectException;

public class JListRequest<T> extends Request<List<T>> {
	private Class<T> responseType;
	private EPCallback<List<T>> handler;
	private String mRequestBody;
	private String url;

	/** Charset for request. */
	private static final String PROTOCOL_CHARSET = "utf-8";
	/** Content type for request. */
	private static final String PROTOCOL_CONTENT_TYPE = String.format(
			"application/json; charset=%s", PROTOCOL_CHARSET);

	/**
	 * Creates a new request.
	 * 
	 * @param method
	 *            the HTTP method to use
	 * @param url
	 *            URL to fetch the JSON from
	 * @param requestData
	 *            A {@link Object} to post and convert into json as the request.
	 *            Null is allowed and indicates no parameters will be posted
	 *            along with request.
	 * @param listener
	 *            Listener to receive the JSON response
	 * @param errorListener
	 *            Error listener, or null to ignore errors.
	 */
	public JListRequest(int method, String url, Object requestData,
			Class<T> responseType, EPCallback<List<T>> listener) {
		super(method, EPClient.getAbsoluteUrl(url), listener);
		try {
			this.url = EPClient.getAbsoluteUrl(url);
			this.mRequestBody = JSON.std.asString(requestData);
		} catch (JSONObjectException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.handler = listener;
		this.responseType = responseType;
	}

	protected Response<List<T>> parseNetworkResponse(NetworkResponse response) {
		String jsonString = null;
		try {
			jsonString = new String(response.data,
					HttpHeaderParser.parseCharset(response.headers));

			return Response.success(
					JSON.std.listOfFrom(responseType, jsonString),
					HttpHeaderParser.parseCacheHeaders(response));
		} catch (Exception e) {
			Log.e(getClass().getSimpleName(),
					"Error when parsing response from url: " + url);
			Log.e(getClass().getSimpleName(), "JSON string: " + jsonString);
			Log.e(getClass().getSimpleName(), "Raw data: " + response.data);

			return Response.error(new ParseError(e));
		}
	}

	@Override
	public byte[] getPostBody() {
		return getBody();
	}

	@Override
	public String getBodyContentType() {
		return PROTOCOL_CONTENT_TYPE;
	}

	@Override
	public byte[] getBody() {
		try {
			return mRequestBody == null ? null : mRequestBody
					.getBytes(PROTOCOL_CHARSET);
		} catch (UnsupportedEncodingException uee) {
			VolleyLog
					.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
							mRequestBody, PROTOCOL_CHARSET);
			return null;
		}
	}

	@Override
	protected void deliverResponse(List<T> response) {
		handler.onSuccess(response);
	}
}